package com.yootk.main;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;

/**
 * 表达式变量操作
 */
public class Demo04_ExpressionVariable {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo03_Expression.class);

    public static void main(String[] args) throws Exception {
//        test1();
//        test2();
//        test3();
//        test4();
        test5();
    }

    /**
     * 定义表达式变量
     */
    public static void test1() {
        String content = "#{ #varA + #varB }";
        ExpressionParser parser = new SpelExpressionParser();
        Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("varA", "Hello");
        context.setVariable("varB", " YOOTK.com");
        String resultA = exp.getValue(context, String.class);
        LOGGER.info("字符串连接结果：{}", resultA);
        context.setVariable("varA", 10.2);
        context.setVariable("varB", 20.3);
        double resultB = exp.getValue(context, Double.class);
        LOGGER.info("数字计算结果：{}", resultB);
    }

    /**
     * 定义根变量
     */
    public static void test2() {
        String content = "#{ #root.contains('yootk') }";
        ExpressionParser parser = new SpelExpressionParser();
        Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);
        EvaluationContext context = new StandardEvaluationContext("yootk.com");     // 使用根变量
        boolean result = exp.getValue(context, Boolean.class);
        LOGGER.info("结果：{}", result);
    }

    /**
     * 实现方法引用处理（传统设计思想）
     */
    public static void test3() throws Exception {
        String content = "#{ #convert('919') }";
        Method method = Integer.class.getMethod("parseInt", String.class);  // 获取指定方法的实例
        ExpressionParser parser = new SpelExpressionParser();
        Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("convert", method);
        int result = exp.getValue(context, Integer.class);
        LOGGER.info("结果：{}", result * 2);
    }

    /**
     * 实现类成员属性的调用
     */
    public static void test4() {
        // java.util.Date类中提供有getTime()方法，所以此处可以直接采用time标记进行属性表示
        String content = "#{ #var.time }";
        ExpressionParser parser = new SpelExpressionParser();
        Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("var", new java.util.Date());
        Long result = exp.getValue(context, Long.class);
        LOGGER.info("结果：{}", result);
    }

    /**
     * 使用Groovy表达式处理null
     */
    public static void test5() {
        // 产生异常的代码
//        {
//            String content = "#{ #var.time }";
//            ExpressionParser parser = new SpelExpressionParser();
//            Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);
//            EvaluationContext context = new StandardEvaluationContext();
//            context.setVariable("var", null);
//            Long result = exp.getValue(context, Long.class);
//            LOGGER.info("结果：{}", result);
//        }
        // 使用Groovy表达式处理null
        {
            // 此时会判断当前变量的内容是否为null，如果是null直接返回null的数据
            // 如果不是null，则正常执行计算处理
            String content = "#{ #var?.time }";
            ExpressionParser parser = new SpelExpressionParser();
            Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);
            EvaluationContext context = new StandardEvaluationContext();
//            context.setVariable("var", new java.util.Date());
            context.setVariable("var", null);
            Long result = exp.getValue(context, Long.class);
            LOGGER.info("结果：{}", result);
        }
    }
}
